/****************************************************************************
 *
 * Spell System
 * Copyright (c) 2007 Antrix Team
 *
 * This file may be distributed under the terms of the Q Public License
 * as defined by Trolltech ASA of Norway and appearing in the file
 * COPYING included in the packaging of this file.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 */

#ifndef __SPELL_H
#define __SPELL_H

#include "SpellFailure.h"

class WorldSession;
class Unit;
class DynamicObj;
class Player;
class Item;
class Group;
class Aura;
/* Spell Ranges:(for 1.10.2)
Range ID|Range|Description
1	   0-0	 Self Only
2	   0-5	 Combat Range
3	   0-20	Short Range
4	   0-30	Medium Range
5	   0-40	Long Range
6	   0-100   Vision Range
7	   0-10	Very Short Range
8	   10-20   Short Range
9	   10-30   Medium Range
10	  10-40   Long Range
11	  0-15	Shorter Range
12	  0-5	 Interact Range
13	  0-50000 Anywhere
14	  0-60	Extra Long Range
34	  0-25	Medium-Short Range
35	  0-35	Medium-Long Range
36	  0-45	Longer Range
37	  0-50	Extended Range
38	  10-25   Extra Medium Range
54	  5-30	Geoff Monster Shoot
74	  8-30	Ranged Weapon
94	  8-40	Sting
95	  8-25	Charge
96	  0-2	 Trap
114	 8-35	Hunter Range Hunter
134	 0-80	Tower 80 Tower
135	 0-100   Tower 100 Tower
*/

/*FLAT PCT
0	x	x
1	x	x
2	x	x
3		 x
4	x
5	x	x
6	x	x
7	x =  x//both add % to crit
8	x	x
9		 x
10   x	x
11   x	x
12   x
13	
14   x	x
15		x
16   x	
17   x
18   x	x
19   x
20		x
21	
22   x	x
23   x(enslave dem)
24	
25
26   x(obsolete)
27		x
*/

//wooohooo, there are 19 spells that actually require to add a proccounter for these 
//first spell catched is "presence of mind"
//an ugly solution would be to add a proc flag to remove aura on event it should expire (like attack or cast) but that is only if count=1
enum SPELL_MODIFIER_TYPE
{
	SMT_DAMAGE_DONE	 =0,// increases the damage done by spell by x% dmg (flat as x dmg)
	SMT_DURATION		=1,// spell	duration increase // GOOD
	//hmm shaman spirit weapon clearly states that this should be parry chance
	SMT_TREAT_REDUCED   =2,// reduces threat generated by this spell by x% // GOOD but need more work
	SMT_ATTACK_POWER_AND_DMG_BONUS=3,// attacker power bonus for ability +x% // Seal of crusader also takes this as dmg bonus + power bonus 
	SMT_BLOCK		   =4,// block additional attack // GOOD and need work //Not used in 2.1.1 ?
	SMT_RANGE		   =5,// spell range bonus // GOOD
	SMT_RADIUS		  =6,// spell radius bonus // GOOD
	SMT_CRITICAL		=7,// critical chance bonus // GOOD //only 1 example in 2.1.1
	SMT_DUMMY		   =8,// dummy effect // needs work is not only pets Hp but effect of spells to
	SMT_NONINTERRUPT	=9,// x% chance not to be interrupted by received damage (no flat)
	SMT_CAST_TIME	   =10,// cast time decrease // GOOD
	SMT_COOLDOWN_DECREASE=11,// cooldown decrease <-probably fully handled by client // GOOD
	SMT_EFFECT		= 12,//used by shaman elemental weapons and another spell
//	SMT_SPEED		   =12,// movement speed, while given spell is active(flat is %) // TODO CHECK! ok this is not speed and is used with 23 misc to sometimes so is odd
	// 13 dont exist spells with it
	SMT_COST			=14,// mana/energy/rage cost reduction // GOOD
	SMT_CRITICAL_DAMAGE =15,// increases critical strike damage bonus (no flat)
	SMT_RESIST		  =16,// enemy resist chance decrease (flat as %) // GOOD need work
	SMT_ADDITIONAL_TARGET=17,// Your Healing Wave will now jump to additional nearby targets. Each jump reduces the effectiveness of the heal by 80% // GOOD
	SMT_TRIGGER		 =18,// adds/increases chance to trigger some spell for example increase chance to apply poisons or entaglin // GOOD need work
	SMT_TIME			=19,// delay for nova, redirection time bonus for totem,maybe smth else // GOOD need work
	SMT_JUMP_REDUCE	 =20,// Increases the amount healed by Chain Heal to targets beyond the first by x%. (no flat)
	//SMT_CAST_TIME2	  =21,// this one looks like cast time...
	SMT_DAMAGE_DONE_PERIODIC=22,// damage done by ability by x% // GOOD but i think is not % so TODO CHECK!
	SMT_UNKNOWN23=23,//increase the target's spell damage and healing by an amount equal to $s1% of their total Spirit." , this one is used with the 12 effect needs some decode
	SMT_PENALTY		 =24,// This is a modifer for the amount of +spell damage applied to the spell group, ill be implementing it soon (fishbait) (it should really have a better name ;) ) // GOOD
	// 25 dont exist spells with it
	// 26 is obsolete stuff
	SMT_EFFECT_BONUS	=27,// mana lost cost per point of damage taken for mana shield,Health or Mana gained from Drain Life and Drain Mana increased by x%.
	SMT_RESIST_DISPEL   =28,// TODO NEEDS WORK :D
};


inline void SM_FFValue(int32 *m, float *v,uint32 group)
{
	if(m == 0) return;

	for(uint32 x=0;x<SPELL_GROUPS;x++)
		if((1<<x) & group)
			(*v)+=m[x];
}

inline void SM_FIValue(int32 *m, int32 *v,uint32 group)
{
	if(m == 0) return;

	for(uint32 x=0;x<SPELL_GROUPS;x++)
		if((1<<x) & group)
			(*v)+=m[x];
}

inline void SM_PIValue(int32 *m, int32 *v,uint32 group)
{
	if(m == 0) return;

	for(uint32 x=0;x<SPELL_GROUPS;x++)
		if((1<<x) & group)
			(*v)+= ((*v)*(m[x]))/100;
}

inline void SM_PFValue(int32*m, float *v,uint32 group)
{
	if(m == 0) return;
	
	for(uint32 x=0;x<SPELL_GROUPS;x++)
		if((1<<x) & group)
			(*v)+= ((*v)*m[x])/100.0;
}

enum SPELL_TYPE
{
	SPELL_TYPE_MELEE,
	SPELL_TYPE_MAGIC,
	SPELL_TYPE_RANGED
};

/*enum SPELL_TYPE
{
	SPELL_TYPE_NONE,
	SPELL_TYPE_MELEE,
	SPELL_TYPE_MAGIC,
	SPELL_TYPE_RANGED
};*/

// value's for SendSpellLog
enum SPELL_LOG
{
	SPELL_LOG_NONE,
	SPELL_LOG_MISS,
	SPELL_LOG_RESIST,
	SPELL_LOG_DODGE,
	SPELL_LOG_PARRY,
	SPELL_LOG_BLOCK,
	SPELL_LOG_EVADE,
	SPELL_LOG_IMMUNE,
	SPELL_LOG_IMMUNE2,
	SPELL_LOG_DEFLECT,
	SPELL_LOG_ABSORB,
	SPELL_LOG_REFLECT
};

enum SpellCastTargetFlags
{
	TARGET_FLAG_SELF			 = 0x0000, // they are checked in following order
	TARGET_FLAG_UNIT			 = 0x0002,
	TARGET_FLAG_ITEM			 = 0x0010,
	TARGET_FLAG_CORPSE		   = 0x0200,
	TARGET_FLAG_OBJECT		   = 0x0800,
	TARGET_FLAG_TRADE_ITEM			 = 0x1000,
	TARGET_FLAG_SOURCE_LOCATION  = 0x0020,
	TARGET_FLAG_DEST_LOCATION	= 0x0040,
	TARGET_FLAG_STRING		   = 0x2000,
	TARGET_FLAG_UNKNOWN			= 0x4000,
	TARGET_FLAG_CORPSE2			= 0x8000
};
enum procFlags
{
	PROC_NULL					   = 0x0,
	PROC_ON_ANY_HOSTILE_ACTION	  = 0x1,
	PROC_ON_GAIN_EXPIERIENCE		= 0x2,
	PROC_ON_MELEE_ATTACK			= 0x4,
	PROC_ON_CRIT_HIT_VICTIM		 = 0x8,
	PROC_ON_CAST_SPELL			  = 0x10,
	PROC_ON_PHYSICAL_ATTACK_VICTIM  = 0x20,
	PROC_ON_RANGED_ATTACK		   = 0x40,
	PROC_ON_UNK_DAMAGE_VICTIM	   = 0x80,//seems to be on ranged dmg victim 99% sure('each melee or ranged attack' -> flag =680 (dec))
	PROC_ON_PHYSICAL_ATTACK		 = 0x100,
	PROC_ON_MELEE_ATTACK_VICTIM	 = 0x200,
	PROC_ON_ANY_ACTION			  = 0x400,
	PROC_UNK_DEFILLED			   = 0x800,
	PROC_ON_CRIT_ATTACK			 = 0x1000,
	PROC_ON_RANGED_ATTACK_VICTIM	= 0x2000,
	PROC_ANYTIME					= 0x4000,
	PROC_UNK2_DEFILLED			  = 0x8000,
	PROC_ON_CAST_SPECIFIC_SPELL	 = 0x10000,
	PROC_ON_SPELL_HIT_VICTIM		= 0x20000,
	PROC_ON_SPELL_CRIT_HIT_VICTIM   = 0x40000,
	PROC_ON_UNK2_DAMAGE_VICTIM	  = 0x80000,
	PROC_ON_ANY_DAMAGE_VICTIM	   = 0x100000,
	PROC_ON_TRAP_TRIGGERED		  = 0x200000,
	PROC_ON_AUTO_SHOT_HIT			= 0x400000,
	PROC_UNUSED2					= 0x800000,
	PROC_REMOVEONUSE				= 0x8000000,//remove prochcharge only when it is used
	PROC_MISC						= 0x10000000,//our custom flag to decide if proc dmg or shield
	PROC_ON_BLOCK_VICTIM			= 0x20000000,//added it as custom, maybe already exists in another form ?
	PROC_ON_SPELL_CRIT_HIT			= 0x40000000,//added it as custom, maybe already exists in another form ?
	PROC_TAGRGET_SELF				= 0x80000000,//our custom flag to decide if proc target is self or victim
};

enum CastInterruptFlags
{
	CAST_INTERRUPT_NULL			= 0x0,
	CAST_INTERRUPT_ON_SILENCE	  = 0x1,
	CAST_INTERRUPT_ON_SLEEP		= 0x2, // could be wrong
	CAST_INTERRUPT_ON_STUNNED	  = 0x4, // could be wrong
	CAST_INTERRUPT_ON_MOVEMENT	 = 0x8,
	CAST_INTERRUPT_ON_DAMAGE_TAKEN = 0x10
};

enum AuraInterruptFlags
{
	AURA_INTERRUPT_NULL					   = 0x0,
	AURA_INTERRUPT_ON_HOSTILE_SPELL_INFLICTED = 0x1,
	AURA_INTERRUPT_ON_ANY_DAMAGE_TAKEN		= 0x2,
	AURA_INTERRUPT_ON_UNK1					= 0x4,
	AURA_INTERRUPT_ON_MOVEMENT				= 0x8, // could be AURA_INTERRUPT_ON_MOVEMENT
	AURA_INTERRUPT_ON_UNK2					= 0x10,
	AURA_INTERRUPT_ON_UNK3					= 0x20,
	AURA_INTERRUPT_ON_UNUSED1				 = 0x40,
	AURA_INTERRUPT_ON_SLOWED				  = 0x80,
	AURA_INTERRUPT_ON_LEAVE_WATER			 = 0x100, // could be AURA_INTERRUPT_ON_LEAVE_CURRENT_SURFACE
	AURA_INTERRUPT_ON_UNUSED2				 = 0x200,
	AURA_INTERRUPT_ON_UNK4					= 0x400,
	AURA_INTERRUPT_ON_UNK5					= 0x800,
	AURA_INTERRUPT_ON_START_ATTACK			= 0x1000,
	AURA_INTERRUPT_ON_UNK6					= 0x2000,
	AURA_INTERRUPT_ON_UNUSED3				 = 0x4000,
	AURA_INTERRUPT_ON_CAST_SPELL			  = 0x8000,
	AURA_INTERRUPT_ON_UNK7					= 0x10000,
	AURA_INTERRUPT_ON_MOUNT				   = 0x20000,
	AURA_INTERRUPT_ON_STAND_UP				= 0x40000,
	AURA_INTERRUPT_ON_LEAVE_AREA			  = 0x80000,
	AURA_INTERRUPT_ON_INVINCIBLE			  = 0x100000,
	AURA_INTERRUPT_ON_STEALTH				 = 0x200000,
	AURA_INTERRUPT_ON_UNK8					= 0x400000,
};

enum ChannelInterruptFlags
{
	CHANNEL_INTERRUPT_NULL  = 0x0,
	CHANNEL_INTERRUPT_ON_1  = 0x1,
	CHANNEL_INTERRUPT_ON_2  = 0x2,
	CHANNEL_INTERRUPT_ON_3  = 0x4,
	CHANNEL_INTERRUPT_ON_4  = 0x8,
	CHANNEL_INTERRUPT_ON_5  = 0x10,
	CHANNEL_INTERRUPT_ON_6  = 0x20,
	CHANNEL_INTERRUPT_ON_7  = 0x40,
	CHANNEL_INTERRUPT_ON_8  = 0x80,
	CHANNEL_INTERRUPT_ON_9  = 0x100,
	CHANNEL_INTERRUPT_ON_10 = 0x200,
	CHANNEL_INTERRUPT_ON_11 = 0x400,
	CHANNEL_INTERRUPT_ON_12 = 0x800,
	CHANNEL_INTERRUPT_ON_13 = 0x1000,
	CHANNEL_INTERRUPT_ON_14 = 0x2000,
	CHANNEL_INTERRUPT_ON_15 = 0x4000,
	CHANNEL_INTERRUPT_ON_16 = 0x8000,
	CHANNEL_INTERRUPT_ON_17 = 0x10000,
	CHANNEL_INTERRUPT_ON_18 = 0x20000
};

enum Attributes
{
	ATTRIBUTES_NULL		   = 0x0,
	ATTRIBUTES_UNK2		   = 0x1,
	ATTRIBUTES_UNK3		   = 0x2, // related to ranged??
	ATTRIBUTE_ON_NEXT_ATTACK  = 0x4,
	ATTRIBUTES_UNK5		   = 0x8,
	ATTRIBUTES_UNK6		   = 0x10,
	ATTRIBUTES_UNK7		   = 0x20, // Reagents??
	ATTRIBUTES_PASSIVE		= 0x40,
	ATTRIBUTES_NO_VISUAL_AURA = 0x80,
	ATTRIBUTES_UNK10		  = 0x100,//seems to be afflicts pet
	ATTRIBUTES_UNK11		  = 0x200, // only appears in shaman imbue weapon spells
	ATTRIBUTES_UNK12		  = 0x400,
	ATTRIBUTES_UNK13		  = 0x800,
	ATTRIBUTES_UNUSED1		= 0x1000,
	ATTRIBUTES_UNUSED2		= 0x2000,
	ATTRIBUTES_UNUSED3		= 0x4000,
	ATTRIBUTES_ONLY_OUTDOORS  = 0x8000,
	ATTRIBUTES_UNK			= 0x10000,
	ATTRIBUTES_REQ_STEALTH	= 0x20000,
	ATTRIBUTES_MUSTBEBEHIND   = 0x40000,//may be wrong
	ATTRIBUTES_UNK21		  = 0x80000,
	ATTRIBUTES_MUSTFACECASTER = 0x100000,//may be wrong
	ATTRIBUTES_UNK23		  = 0x200000,
	ATTRIBUTES_UNK24		  = 0x400000,
	ATTRIBUTES_UNK25		  = 0x800000,
	ATTRIBUTES_UNK26		  = 0x1000000,
	ATTRIBUTES_UNK27		  = 0x2000000,
	ATTRIBUTES_UNK28		  = 0x4000000,
	ATTRIBUTES_UNK29		  = 0x8000000,
	ATTRIBUTES_REQ_OOC		= 0x10000000, //	 ATTRIBUTES_REQ_OUT_OF_COMBAT
	ATTRIBUTES_UNK31		  = 0x20000000,
	ATTRIBUTES_UNK32		  = 0x40000000,
	ATTRIBUTES_UNUSED9		= 0x80000000,
};

enum AttributesEx
{
	ATTRIBUTESEX_NULL						 = 0x0,
	ATTRIBUTESEX_UNK2						 = 0x1,
	ATTRIBUTEEX_DRAIN_WHOLE_MANA			  = 0x2,
	ATTRIBUTESEX_UNK4						 = 0x4,
	ATTRIBUTESEX_UNK5						 = 0x8,
	ATTRIBUTESEX_UNK6						 = 0x10,
	ATTRIBUTESEX_REMAIN_STEALTHED			  = 0x20,
	ATTRIBUTESEX_UNK8						 = 0x40,
	ATTRIBUTESEX_UNK9						 = 0x80,
	ATTRIBUTESEX_UNK10						= 0x100,
	ATTRIBUTESEX_UNK11						= 0x200,
	ATTRIBUTESEX_UNK12						= 0x400,
	ATTRIBUTESEX_UNK13						= 0x800,
	ATTRIBUTESEX_UNK14						= 0x1000, // related to pickpocket
	ATTRIBUTESEX_UNK15						= 0x2000, // related to remote control
	ATTRIBUTESEX_UNK16						= 0x4000,
	ATTRIBUTESEX_UNK17						= 0x8000,
	ATTRIBUTESEX_UNK18						= 0x10000, 
	ATTRIBUTESEX_REMAIN_OOC				   = 0x20000,
	ATTRIBUTESEX_UNK20						= 0x40000,
	ATTRIBUTESEX_UNK21						= 0x80000,
	ATTRIBUTESEX_UNK22						= 0x100000, // related to "Finishing move" and "Instantly overpowers"
	ATTRIBUTESEX_UNK23						= 0x200000,
	ATTRIBUTESEX_UNK24						= 0x400000, // only related to "Finishing move"
	ATTRIBUTESEX_UNK25						= 0x800000, // related to spells like "ClearAllBuffs"
	ATTRIBUTESEX_UNK26						= 0x1000000, // FISHING SPELLS
	ATTRIBUTESEX_UNK27						= 0x2000000, // related to "Detect" spell
	ATTRIBUTESEX_UNK28						= 0x4000000,
	ATTRIBUTESEX_UNK29						= 0x8000000,
	ATTRIBUTESEX_UNK30						= 0x10000000,
	ATTRIBUTESEX_UNK31						= 0x20000000,
	ATTRIBUTESEX_UNK32						= 0x40000000, // Overpower
};

enum Flags3
{
	FLAGS3_NULL			   = 0x0,
	FLAGS3_UNK2			   = 0x1,
	FLAGS3_UNK3			   = 0x2, // related to shadow stuff
	FLAGS3_UNK4			   = 0x4, // request pet maybe
	FLAGS3_UNK5			   = 0x8,
	FLAGS3_UNK6			   = 0x10,
	FLAGS3_ACTIVATE_AUTO_SHOT = 0x20,
	FLAGS3_UNK8			   = 0x40, //Polymorph spells
	FLAGS3_UNK9			   = 0x80,
	FLAGS3_UNUSED1			= 0x100,
	FLAGS3_UNUSED2			= 0x200,
	FLAGS3_UNK12			  = 0x400, // something with beast taming maybe requires beast focus
	FLAGS3_UNK13			  = 0x800,
	FLAGS3_UNK14			  = 0x1000, // swipe / Cleave spells
	FLAGS3_UNK15			  = 0x2000,
	FLAGS3_UNK16			  = 0x4000,
	FLAGS3_UNUSED3			= 0x8000,
	FLAGS3_UNK18			  = 0x10000, // something with beast taming maybe requires beast focus
	FLAGS3_REQ_RANGED_WEAPON  = 0x20000, // this is shit and has nothing to do with auto shot
	FLAGS3_UNK20			  = 0x40000,
	FLAGS3_UNK21			  = 0x80000,
	FLAGS3_REQ_BEHIND_TARGET  = 0x100000,
	FLAGS3_UNK23			  = 0x200000,
	FLAGS3_UNK24			  = 0x400000,
	FLAGS3_UNK25			  = 0x800000,
	FLAGS3_UNK26			  = 0x1000000,
	FLAGS3_UNK27			  = 0x2000000,
	FLAGS3_UNK28			  = 0x4000000,
	FLAGS3_UNK29			  = 0x8000000, // something with fishing
	FLAGS3_UNK30			  = 0x10000000,
	FLAGS3_UNK31			  = 0x20000000,
	FLAGS3_UNK32			  = 0x40000000,
	
};

enum SpellCastFlags
{
	CAST_FLAG_UNKNOWN1		   = 0x2,
	CAST_FLAG_UNKNOWN2		   = 0x10, // no idea yet, i saw it in blizzard spell
	CAST_FLAG_AMMO			   = 0x20 // load ammo display id (uint32) and ammo inventory type (uint32)
};

enum School
{
	SCHOOL_NORMAL = 0,
	SCHOOL_HOLY   = 1,
	SCHOOL_FIRE   = 2,
	SCHOOL_NATURE = 3,
	SCHOOL_FROST  = 4,
	SCHOOL_SHADOW = 5,
	SCHOOL_ARCANE = 6
};

enum ReplenishType
{
	REPLENISH_UNDEFINED = 0,
	REPLENISH_HEALTH	= 20,
	REPLENISH_MANA	  = 21,
	REPLENISH_RAGE	  = 22 //don't know if rage is 22 or what, but will do for now
};

enum SpellTargetType
{
	TARGET_TYPE_NULL	   = 0x0,
	TARGET_TYPE_BEAST	  = 0x1,
	TARGET_TYPE_DRAGONKIN  = 0x2,
	TARGET_TYPE_DEMON	  = 0x4,
	TARGET_TYPE_ELEMENTAL  = 0x8,
	TARGET_TYPE_GIANT	  = 0x10,
	TARGET_TYPE_UNDEAD	 = 0x20,
	TARGET_TYPE_HUMANOID   = 0x40,
	TARGET_TYPE_CRITTER	= 0x80,
	TARGET_TYPE_MECHANICAL = 0x100,
};

/****************SpellExtraFlags*****************/
/* SpellExtraFlags defines					  */
/*											  */
/* Used for infront check and other checks	  */
/* when they are not in spell.dbc			   */
/*											  */
/************************************************/
#define SPELL_EXTRA_INFRONT 1
#define SPELL_EXTRA_BEHIND  2
#define SPELL_EXTRA_UNDEF0  4 // not used yet
#define SPELL_EXTRA_UNDEF1  8 // not used yet


/***************Ranged spellid*******************/
/* Note: These spell id's are checked for 2.0.6 */
/************************************************/
#define SPELL_RANGED_BOW		3018
#define SPELL_RANGED_GUN		3018
#define SPELL_RANGED_CROSSBOW   3018
#define SPELL_RANGED_THROW	  2764
#define SPELL_RANGED_WAND	   5019

struct TeleportCoords
{
	uint32 id;
	uint32 mapId;
	float x;
	float y;
	float z;
};

struct TotemSpells
{
	uint32 spellId;
	uint32 spellToCast[3];
};

enum LOCKTYPES{
		LOCKTYPE_PICKLOCK			   =1,
		LOCKTYPE_HERBALISM			  =2,
		LOCKTYPE_MINING				 =3,
		LOCKTYPE_DISARM_TRAP			=4,
		LOCKTYPE_OPEN				   =5,
		LOCKTYPE_TREASURE			   =6,
		LOCKTYPE_CALCIFIED_ELVEN_GEMS   =7,
		LOCKTYPE_CLOSE				  =8,
		LOCKTYPE_ARM_TRAP			   =9,
		LOCKTYPE_QUICK_OPEN			 =10,
		LOCKTYPE_QUICK_CLOSE			=11,
		LOCKTYPE_OPEN_TINKERING		 =12,
		LOCKTYPE_OPEN_KNEELING		  =13,
		LOCKTYPE_OPEN_ATTACKING		 =14,
		LOCKTYPE_GAHZRIDIAN			 =15,
		LOCKTYPE_BLASTING			   =16,
		LOCKTYPE_SLOW_OPEN			  =17,
		LOCKTYPE_SLOW_CLOSE			 =18
};

enum SpellEffects
{
	SPELL_EFFECT_NULL = 0,
	SPELL_EFFECT_INSTANT_KILL,			  //	1
	SPELL_EFFECT_SCHOOL_DAMAGE,			 //	2	
	SPELL_EFFECT_DUMMY,					 //	3	
	SPELL_EFFECT_PORTAL_TELEPORT,		   //	4	
	SPELL_EFFECT_TELEPORT_UNITS,			//	5	
	SPELL_EFFECT_APPLY_AURA,				//	6	
	SPELL_EFFECT_ENVIRONMENTAL_DAMAGE,	  //	7	
	SPELL_EFFECT_POWER_DRAIN,			   //	8	
	SPELL_EFFECT_HEALTH_LEECH,			  //	9	
	SPELL_EFFECT_HEAL,					  //	10	
	SPELL_EFFECT_BIND,					  //	11	
	SPELL_EFFECT_PORTAL,					//	12
	SPELL_EFFECT_RITUAL_BASE,			   //	13
	SPELL_EFFECT_RITUAL_SPECIALIZE,		 //	14
	SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL,	//	15
	SPELL_EFFECT_QUEST_COMPLETE,			//	16	
	SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL,	//	17	
	SPELL_EFFECT_RESURRECT,				 //	18	
	SPELL_EFFECT_ADD_EXTRA_ATTACKS,		 //	19	
	SPELL_EFFECT_DODGE,					 //	20	
	SPELL_EFFECT_EVADE,					 //	21	
	SPELL_EFFECT_PARRY,					 //	22	
	SPELL_EFFECT_BLOCK,					 //	23	
	SPELL_EFFECT_CREATE_ITEM,			   //	24	
	SPELL_EFFECT_WEAPON,					//	25
	SPELL_EFFECT_DEFENSE,				   //	26
	SPELL_EFFECT_PERSISTENT_AREA_AURA,	  //	27	
	SPELL_EFFECT_SUMMON,					//	28	
	SPELL_EFFECT_LEAP,					  //	29	
	SPELL_EFFECT_ENERGIZE,				  //	30	
	SPELL_EFFECT_WEAPON_PERCENT_DAMAGE,	 //	31	
	SPELL_EFFECT_TRIGGER_MISSILE,		   //	32	
	SPELL_EFFECT_OPEN_LOCK,				 //	33	
	SPELL_EFFECT_TRANSFORM_ITEM,			//	34	
	SPELL_EFFECT_APPLY_AREA_AURA,		   //	35	
	SPELL_EFFECT_LEARN_SPELL,			   //	36	
	SPELL_EFFECT_SPELL_DEFENSE,			 //	37	
	SPELL_EFFECT_DISPEL,					//	38	
	SPELL_EFFECT_LANGUAGE,				  //	39
	SPELL_EFFECT_DUAL_WIELD,				//	40	
	SPELL_EFFECT_SUMMON_WILD,			   //	41	
	SPELL_EFFECT_SUMMON_GUARDIAN,		   //	42	
	SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER,	//43
	SPELL_EFFECT_SKILL_STEP,					//44	
	SPELL_EFFECT_UNDEFINED_45,			  //	45	
	SPELL_EFFECT_SPAWN,					 //	46
	SPELL_EFFECT_TRADE_SKILL,			   //	47
	SPELL_EFFECT_STEALTH,				   //	48
	SPELL_EFFECT_DETECT,					//	49
	SPELL_EFFECT_SUMMON_OBJECT,			 //	50	
	//SPELL_EFFECT_TRANS_DOOR,			  //	50	
	SPELL_EFFECT_FORCE_CRITICAL_HIT,		//	51
	SPELL_EFFECT_GUARANTEE_HIT,			 //	52
	SPELL_EFFECT_ENCHANT_ITEM,			  //	53	
	SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY,	//	54	
	SPELL_EFFECT_TAMECREATURE,			  //	55	
	SPELL_EFFECT_SUMMON_PET,				//	56	
	SPELL_EFFECT_LEARN_PET_SPELL,		   //	57	
	SPELL_EFFECT_WEAPON_DAMAGE,			 //	58	
	SPELL_EFFECT_OPEN_LOCK_ITEM,			//	59	
	SPELL_EFFECT_PROFICIENCY,			   //	60
	SPELL_EFFECT_SEND_EVENT,				//	61	
	SPELL_EFFECT_POWER_BURN,				//	62
	SPELL_EFFECT_THREAT,					//	63
	SPELL_EFFECT_TRIGGER_SPELL,			 //	64	
	SPELL_EFFECT_HEALTH_FUNNEL,			 //	65
	SPELL_EFFECT_POWER_FUNNEL,			  //	66
	SPELL_EFFECT_HEAL_MAX_HEALTH,		   //	67	
	SPELL_EFFECT_INTERRUPT_CAST,			//	68
	SPELL_EFFECT_DISTRACT,				  //	69
	SPELL_EFFECT_PULL,					  //	70
	SPELL_EFFECT_PICKPOCKET,				//	71
	SPELL_EFFECT_ADD_FARSIGHT,			  //	72
	SPELL_EFFECT_SUMMON_POSSESSED,		  //	73	
	SPELL_EFFECT_SUMMON_TOTEM,			  //	74	
	SPELL_EFFECT_HEAL_MECHANICAL,		   //	75
	SPELL_EFFECT_SUMMON_OBJECT_WILD,		//	76
	SPELL_EFFECT_SCRIPT_EFFECT,			 //	77	
	SPELL_EFFECT_ATTACK,					//	78
	SPELL_EFFECT_SANCTUARY,				 //	79
	SPELL_EFFECT_ADD_COMBO_POINTS,		  //	80	
	SPELL_EFFECT_CREATE_HOUSE,			  //	81
	SPELL_EFFECT_BIND_SIGHT,				//	82
	SPELL_EFFECT_DUEL,					  //	83
	SPELL_EFFECT_STUCK,					 //	84
	SPELL_EFFECT_SUMMON_PLAYER,			 //	85
	SPELL_EFFECT_ACTIVATE_OBJECT,		   //	86
	SPELL_EFFECT_SUMMON_TOTEM_SLOT1,		//	87	
	SPELL_EFFECT_SUMMON_TOTEM_SLOT2,		//	88	
	SPELL_EFFECT_SUMMON_TOTEM_SLOT3,		//	89	
	SPELL_EFFECT_SUMMON_TOTEM_SLOT4,		//	90	
	SPELL_EFFECT_THREAT_ALL,				//	91
	SPELL_EFFECT_ENCHANT_HELD_ITEM,		 //	92
	SPELL_EFFECT_SUMMON_PHANTASM,		   //	93
	SPELL_EFFECT_SELF_RESURRECT,			//	94	
	SPELL_EFFECT_SKINNING,				  //	95	
	SPELL_EFFECT_CHARGE,					//	96	
	SPELL_EFFECT_SUMMON_CRITTER,			//	97	
	SPELL_EFFECT_KNOCK_BACK,				//	98	
	SPELL_EFFECT_DISENCHANT,				//	99	
	SPELL_EFFECT_INEBRIATE,				 //	100	
	SPELL_EFFECT_FEED_PET,				  //	101
	SPELL_EFFECT_DISMISS_PET,			   //	102
	SPELL_EFFECT_REPUTATION,				//	103
	SPELL_EFFECT_SUMMON_OBJECT_SLOT1,	   //	104
	SPELL_EFFECT_SUMMON_OBJECT_SLOT2,	   //	105
	SPELL_EFFECT_SUMMON_OBJECT_SLOT3,	   //	106
	SPELL_EFFECT_SUMMON_OBJECT_SLOT4,	   //	107
	SPELL_EFFECT_DISPEL_MECHANIC,		   //	108	
	SPELL_EFFECT_SUMMON_DEAD_PET,		   //	109
	SPELL_EFFECT_DESTROY_ALL_TOTEMS,		//110
	SPELL_EFFECT_DURABILITY_DAMAGE,		 //111
	SPELL_EFFECT_SUMMON_DEMON,			  //112	
	SPELL_EFFECT_RESURRECT_FLAT,			//113	
	SPELL_EFFECT_ATTACK_ME,				 //114
	SPELL_EFFECT_DURABILITY_DAMAGE_PCT,	 //115
	SPELL_EFFECT_SKIN_PLAYER_CORPSE,		//116
	SPELL_EFFECT_SPIRIT_HEAL,			   //117
	SPELL_EFFECT_SKILL,					 //118
	SPELL_EFFECT_APPLY_PET_AURA,			//119	
	SPELL_EFFECT_TELEPORT_GRAVEYARD,		//120
	SPELL_EFFECT_DUMMYMELEE,				//121
	SPELL_EFFECT_UNKNOWN1,				  //122
	SPELL_EFFECT_UNKNOWN2,				  //123
	SPELL_EFFECT_UNKNOWN3,				  //124
	SPELL_EFFECT_UNKNOWN4,				  //125
	SPELL_EFFECT_UNKNOWN5,				  //126
	SPELL_EFFECT_PROSPECTING,			  //127
	SPELL_EFFECT_UNKNOWN7,				  //128
	SPELL_EFFECT_UNKNOWN8,				  //129
	SPELL_EFFECT_UNKNOWN9,				  //129
	SPELL_EFFECT_UNKNOWN10,				 //130
	SPELL_EFFECT_UNKNOWN11,				 //131
	SPELL_EFFECT_UNKNOWN12,				 //132
	SPELL_EFFECT_UNKNOWN13,				 //133
	SPELL_EFFECT_UNKNOWN14,				 //134
	SPELL_EFFECT_UNKNOWN15,				 //135
	TOTAL_SPELL_EFFECTS,					//136
};

enum SPELL_ENTRY
{
	SPELL_ENTRY_Id,
	SPELL_ENTRY_School,
	SPELL_ENTRY_Category,
	SPELL_ENTRY_field4,
	SPELL_ENTRY_DispelType,
	SPELL_ENTRY_MechanicsType,
	SPELL_ENTRY_Attributes,
	SPELL_ENTRY_AttributesEx,
	SPELL_ENTRY_Flags3,
	SPELL_ENTRY_field10,
	SPELL_ENTRY_field11,
	SPELL_ENTRY_unk201_1,
	SPELL_ENTRY_UNK12,
	SPELL_ENTRY_UNK13,
	SPELL_ENTRY_Targets,
	SPELL_ENTRY_TargetCreatureType,
	SPELL_ENTRY_RequiresSpellFocus,
	SPELL_ENTRY_CasterAuraState,
	SPELL_ENTRY_TargetAuraState,
	SPELL_ENTRY_unk201_2,
	SPELL_ENTRY_unk201_3,
	SPELL_ENTRY_CastingTimeIndex,
	SPELL_ENTRY_RecoveryTime,
	SPELL_ENTRY_CategoryRecoveryTime,
	SPELL_ENTRY_InterruptFlags,
	SPELL_ENTRY_AuraInterruptFlags,
	SPELL_ENTRY_ChannelInterruptFlags,
	SPELL_ENTRY_procFlags,
	SPELL_ENTRY_procChance,
	SPELL_ENTRY_procCharges,
	SPELL_ENTRY_maxLevel,
	SPELL_ENTRY_baseLevel,
	SPELL_ENTRY_spellLevel,
	SPELL_ENTRY_DurationIndex,
	SPELL_ENTRY_powerType,
	SPELL_ENTRY_manaCost,
	SPELL_ENTRY_manaCostPerlevel,
	SPELL_ENTRY_manaPerSecond,
	SPELL_ENTRY_manaPerSecondPerLevel,
	SPELL_ENTRY_rangeIndex,
	SPELL_ENTRY_speed,
	SPELL_ENTRY_modalNextSpell,
	SPELL_ENTRY_maxstack,
	SPELL_ENTRY_Totem_1,
	SPELL_ENTRY_Totem_2,
	SPELL_ENTRY_Reagent_1,
	SPELL_ENTRY_Reagent_2,
	SPELL_ENTRY_Reagent_3,
	SPELL_ENTRY_Reagent_4,
	SPELL_ENTRY_Reagent_5,
	SPELL_ENTRY_Reagent_6,
	SPELL_ENTRY_Reagent_7,
	SPELL_ENTRY_Reagent_8,
	SPELL_ENTRY_ReagentCount_1,
	SPELL_ENTRY_ReagentCount_2,
	SPELL_ENTRY_ReagentCount_3,
	SPELL_ENTRY_ReagentCount_4,
	SPELL_ENTRY_ReagentCount_5,
	SPELL_ENTRY_ReagentCount_6,
	SPELL_ENTRY_ReagentCount_7,
	SPELL_ENTRY_ReagentCount_8,
	SPELL_ENTRY_EquippedItemClass,
	SPELL_ENTRY_EquippedItemSubClass,
	SPELL_ENTRY_RequiredItemFlags,
	SPELL_ENTRY_Effect_1,
	SPELL_ENTRY_Effect_2,
	SPELL_ENTRY_Effect_3,
	SPELL_ENTRY_EffectDieSides_1,
	SPELL_ENTRY_EffectDieSides_2,
	SPELL_ENTRY_EffectDieSides_3,
	SPELL_ENTRY_EffectBaseDice_1,
	SPELL_ENTRY_EffectBaseDice_2,
	SPELL_ENTRY_EffectBaseDice_3,
	SPELL_ENTRY_EffectDicePerLevel_1,
	SPELL_ENTRY_EffectDicePerLevel_2,
	SPELL_ENTRY_EffectDicePerLevel_3,
	SPELL_ENTRY_EffectRealPointsPerLevel_1,
	SPELL_ENTRY_EffectRealPointsPerLevel_2,
	SPELL_ENTRY_EffectRealPointsPerLevel_3,
	SPELL_ENTRY_EffectBasePoints_1,
	SPELL_ENTRY_EffectBasePoints_2,
	SPELL_ENTRY_EffectBasePoints_3,
	SPELL_ENTRY_EffectMechanic_1,
	SPELL_ENTRY_EffectMechanic_2,
	SPELL_ENTRY_EffectMechanic_3,
	SPELL_ENTRY_EffectImplicitTargetA_1,
	SPELL_ENTRY_EffectImplicitTargetA_2,
	SPELL_ENTRY_EffectImplicitTargetA_3,
	SPELL_ENTRY_EffectImplicitTargetB_1,
	SPELL_ENTRY_EffectImplicitTargetB_2,
	SPELL_ENTRY_EffectImplicitTargetB_3,
	SPELL_ENTRY_EffectRadiusIndex_1,
	SPELL_ENTRY_EffectRadiusIndex_2, 
	SPELL_ENTRY_EffectRadiusIndex_3, 
	SPELL_ENTRY_EffectApplyAuraName_1,
	SPELL_ENTRY_EffectApplyAuraName_2,
	SPELL_ENTRY_EffectApplyAuraName_3,
	SPELL_ENTRY_EffectAmplitude_1,
	SPELL_ENTRY_EffectAmplitude_2,
	SPELL_ENTRY_EffectAmplitude_3,
	SPELL_ENTRY_Effectunknown_1,
	SPELL_ENTRY_Effectunknown_2,
	SPELL_ENTRY_Effectunknown_3,
	SPELL_ENTRY_EffectChainTarget_1,
	SPELL_ENTRY_EffectChainTarget_2,
	SPELL_ENTRY_EffectChainTarget_3,
	SPELL_ENTRY_EffectSpellGroupRelation_1,
	SPELL_ENTRY_EffectSpellGroupRelation_2,
	SPELL_ENTRY_EffectSpellGroupRelation_3,
	SPELL_ENTRY_EffectMiscValue_1,
	SPELL_ENTRY_EffectMiscValue_2,
	SPELL_ENTRY_EffectMiscValue_3,
	SPELL_ENTRY_EffectTriggerSpell_1,
	SPELL_ENTRY_EffectTriggerSpell_2,
	SPELL_ENTRY_EffectTriggerSpell_3,
	SPELL_ENTRY_EffectPointsPerComboPoint_1,
	SPELL_ENTRY_EffectPointsPerComboPoint_2,
	SPELL_ENTRY_EffectPointsPerComboPoint_3,
	SPELL_ENTRY_SpellVisual,
	SPELL_ENTRY_field114,
	SPELL_ENTRY_dummy,
	SPELL_ENTRY_CoSpell,
	SPELL_ENTRY_spellPriority,
	SPELL_ENTRY_Name,
	SPELL_ENTRY_NameAlt1,
	SPELL_ENTRY_NameAlt2,
	SPELL_ENTRY_NameAlt3,
	SPELL_ENTRY_NameAlt4,
	SPELL_ENTRY_NameAlt5,
	SPELL_ENTRY_NameAlt6,
	SPELL_ENTRY_NameAlt7,
	SPELL_ENTRY_NameFlags,
	SPELL_ENTRY_Rank,
	SPELL_ENTRY_RankAlt1,
	SPELL_ENTRY_RankAlt2,
	SPELL_ENTRY_RankAlt3,
	SPELL_ENTRY_RankAlt4,
	SPELL_ENTRY_RankAlt5,
	SPELL_ENTRY_RankAlt6,
	SPELL_ENTRY_RankAlt7,
	SPELL_ENTRY_RankFlags,
	SPELL_ENTRY_Description,
	SPELL_ENTRY_DescriptionAlt1,
	SPELL_ENTRY_DescriptionAlt2,
	SPELL_ENTRY_DescriptionAlt3,
	SPELL_ENTRY_DescriptionAlt4,
	SPELL_ENTRY_DescriptionAlt5,
	SPELL_ENTRY_DescriptionAlt6,
	SPELL_ENTRY_DescriptionAlt7,
	SPELL_ENTRY_DescriptionFlags,
	SPELL_ENTRY_BuffDescription,
	SPELL_ENTRY_BuffDescriptionAlt1,
	SPELL_ENTRY_BuffDescriptionAlt2,
	SPELL_ENTRY_BuffDescriptionAlt3,
	SPELL_ENTRY_BuffDescriptionAlt4,
	SPELL_ENTRY_BuffDescriptionAlt5,
	SPELL_ENTRY_BuffDescriptionAlt6,
	SPELL_ENTRY_BuffDescriptionAlt7,
	SPELL_ENTRY_buffdescflags,
	SPELL_ENTRY_ManaCostPercentage,
	SPELL_ENTRY_unkflags,
	SPELL_ENTRY_StartRecoveryTime,
	SPELL_ENTRY_StartRecoveryCategory,
	SPELL_ENTRY_SpellFamilyName,
	SPELL_ENTRY_SpellGroupType,
	SPELL_ENTRY_unkne,
	SPELL_ENTRY_MaxTargets,
	SPELL_ENTRY_Spell_Dmg_Type,
	SPELL_ENTRY_FG,
	SPELL_ENTRY_FH,
	SPELL_ENTRY_dmg_multiplier_1,
	SPELL_ENTRY_dmg_multiplier_2,
	SPELL_ENTRY_dmg_multiplier_3,
	SPELL_ENTRY_FL,
	SPELL_ENTRY_FM,
	SPELL_ENTRY_FN,
	SPELL_ENTRY_unk201_4,
	SPELL_ENTRY_unk201_5,
	SPELL_ENTRY_unk201_6
};

// lets make this bitwise for more fun
enum SpellTypes
{
	SPELL_TYPE_NONE		 = 0,
	SPELL_TYPE_SEAL		 = 1,
	SPELL_TYPE_ASPECT	   = 2,
	SPELL_TYPE_BLESSING	 = 4,
	SPELL_TYPE_CURSE		= 8,
	SPELL_TYPE_STING		= 16,
	SPELL_TYPE_ARMOR		= 32,
	SPELL_TYPE_AURA		 = 64,
	//hmm these could be named simply incompatible spells. One active at a time
	SPELL_TYPE_MARK_GIFT			= 128,
	SPELL_TYPE_TRACK				= 256,
	SPELL_TYPE_HUNTER_TRAP			= 512,
	SPELL_TYPE_MAGE_INTEL			= 1024,
	SPELL_TYPE_MAGE_MAGI			= 2048,
	SPELL_TYPE_MAGE_WARDS			= 4096,
	SPELL_TYPE_PRIEST_SH_PPROT		= 8192,
	SPELL_TYPE_SHIELD				= 16384,
	SPELL_TYPE_FORTITUDE			= 32768,
	SPELL_TYPE_SPIRIT				= 65536,
	SPELL_TYPE_MAGE_AMPL_DUMP		= 131072,
	SPELL_TYPE_WARLOCK_IMMOLATE		= 262144, //maybe there is a better way to trigger the aurastate for imolate spell
};

inline bool IsInrange(float x1,float y1, float z1, Object * o,float square_r)
{
	float r = o->GetDistanceSq(x1, y1, z1);
	return ( r<=square_r);	
}

inline bool IsInrange(float x1,float y1, float z1,float x2,float y2, float z2,float square_r)
{
	float t;
	float r;
	t=x1-x2;
	r=t*t;
	t=y1-y2;
	r+=t*t;
	t=z1-z2;
	r+=t*t;
	return ( r<=square_r);
}
	
inline bool IsInrange(Object * o1,Object * o2,float square_r)
{
	return IsInrange(o1->GetPositionX(),o1->GetPositionY(),o1->GetPositionZ(),
		o2->GetPositionX(),o2->GetPositionY(),o2->GetPositionZ(),square_r);
}

class SpellCastTargets
{
public:
	void read ( WorldPacket & data,uint64 caster );
	void write ( WorldPacket & data);

	SpellCastTargets() : m_targetMask(0), m_unitTarget(0), m_itemTarget(0), m_srcX(0), m_srcY(0), m_srcZ(0),
		m_destX(0), m_destY(0), m_destZ(0) {}

	SpellCastTargets(uint16 TargetMask, uint64 unitTarget, uint64 itemTarget, float srcX, float srcY,
		float srcZ, float destX, float destY, float destZ) : m_targetMask(TargetMask), m_unitTarget(unitTarget),
		m_itemTarget(itemTarget), m_srcX(srcX), m_srcY(srcY), m_srcZ(srcZ), m_destX(destX), m_destY(destY), m_destZ(destZ) {}

	SpellCastTargets(uint64 unitTarget) : m_targetMask(0x2), m_unitTarget(unitTarget), m_itemTarget(0),
		m_srcX(0), m_srcY(0), m_srcZ(0), m_destX(0), m_destY(0), m_destZ(0) {}

	SpellCastTargets(WorldPacket & data, uint64 caster) : m_targetMask(0), m_unitTarget(0), m_itemTarget(0), m_srcX(0), m_srcY(0), m_srcZ(0),
		m_destX(0), m_destY(0), m_destZ(0)
	{
		read(data, caster);
	}

	SpellCastTargets& operator=(const SpellCastTargets &target)
	{
		m_unitTarget = target.m_unitTarget;
		m_itemTarget = target.m_itemTarget;

		m_srcX = target.m_srcX;
		m_srcY = target.m_srcY;
		m_srcZ = target.m_srcZ;

		m_destX = target.m_destX;
		m_destY = target.m_destY;
		m_destZ = target.m_destZ;

		m_strTarget = target.m_strTarget;

		m_targetMask = target.m_targetMask;

		return *this;
	}

	uint16 m_targetMask;
	uint64 m_unitTarget;
	uint64 m_itemTarget;
	float m_srcX, m_srcY, m_srcZ;
	float m_destX, m_destY, m_destZ;
	std::string m_strTarget;

};

enum SpellState
{
	SPELL_STATE_NULL	  = 0,
	SPELL_STATE_PREPARING = 1,
	SPELL_STATE_CASTING   = 2,
	SPELL_STATE_FINISHED  = 3,
	SPELL_STATE_IDLE	  = 4
};

enum ShapeshiftForm
{
	FORM_CAT			  = 1,
	FORM_TREE			 = 2,
	FORM_TRAVEL		   = 3,
	FORM_AQUA			 = 4,
	FORM_BEAR			 = 5,
	FORM_AMBIENT		  = 6,
	FORM_GHOUL			= 7,
	FORM_DIREBEAR		 = 8,
	FORM_CREATUREBEAR	 = 14,
	FORM_GHOSTWOLF		= 16,
	FORM_BATTLESTANCE	 = 17,
	FORM_DEFENSIVESTANCE  = 18,
	FORM_BERSERKERSTANCE  = 19,
	FORM_SWIFT			= 27,
	FORM_SHADOW		   = 28,
	FORM_FLIGHT		   = 29,
	FORM_STEALTH		  = 30,
	FORM_MOONKIN		  = 31,
	FORM_SPIRITOFREDEMPTION	= 32,
};

enum DISPEL_TYPE
{
	DISPEL_ZGTRINKETS = -1,
	DISPEL_NULL,
	DISPEL_MAGIC,
	DISPEL_CURSE,
	DISPEL_DISEASE,
	DISPEL_POISON,
	DISPEL_STEALTH,
	DISPEL_INVISIBILTY,
	DISPEL_ALL,
	DISPEL_SPECIAL_NPCONLY,
	DISPEL_FRENZY,
};

enum DISPEL_MECHANIC_TYPE
{
	DISPEL_MECHANIC_CHARM	   = 1,
	DISPEL_MECHANIC_FEAR		= 5,
	DISPEL_MECHANIC_ROOT		= 7,
	DISPEL_MECHANIC_SLEEP	   = 10,
	DISPEL_MECHANIC_SNARE	   = 11,
	DISPEL_MECHANIC_STUN		= 12,
	DISPEL_MECHANIC_KNOCKOUT	= 14,
	DISPEL_MECHANIC_BLEED	   = 15,
	DISPEL_MECHANIC_POLYMORPH   = 17,
	DISPEL_MECHANIC_BANISH	  = 18,
	DISPEL_MECHANIC_MOUNTED	 = 21,
};
enum MECHANICS
{
	MECHANIC_CHARMED = 1,
	MECHANIC_DISORIENTED,
	MECHANIC_DISARMED,
	MECHANIC_DISTRACED,
	MECHANIC_FLEEING,
	MECHANIC_CLUMSY,
	MECHANIC_ROOTED,
	MECHANIC_PACIFIED,
	MECHANIC_SILENCED,
	MECHANIC_ASLEEP,
	MECHANIC_ENSNARED,
	MECHANIC_STUNNED,
	MECHANIC_FROZEN,
	MECHANIC_INCAPACIPATED,
	MECHNAIC_BLEEDING,
	MECHANIC_HEALING,
	MECHANIC_POLYMORPHED,
	MECHANIC_BANISHED,
	MECHANIC_SHIELDED,
	MECHANIC_SHACKLED,
	MECHANIC_MOUNTED,
	MECHANIC_SEDUCED,
	MECHANIC_TURNED,
	MECHANIC_HORRIFIED,
	MECHANIC_INVULNARABLE,
	MECHANIC_INTERRUPTED,
	MECHANIC_DAZED
};

typedef enum {
   EFF_TARGET_NONE						= 0,
   EFF_TARGET_SELF						= 1,
   EFF_TARGET_PET						= 5,
   EFF_TARGET_SINGLE_ENEMY				= 6,
   EFF_TARGET_ALL_ENEMY_IN_AREA         = 15,
   EFF_TARGET_ALL_ENEMY_IN_AREA_INSTANT	= 16,
   EFF_TARGET_ALL_PARTY_AROUND_CASTER   = 20,
   EFF_TARGET_SINGLE_FRIEND				= 21,
   EFF_TARGET_ALL_ENEMIES_AROUND_CASTER = 22,
   EFF_TARGET_GAMEOBJECT				= 23,
   EFF_TARGET_IN_FRONT_OF_CASTER        = 24,
   EFF_TARGET_DUEL						= 25,//Dont know the real name!!!
   EFF_TARGET_GAMEOBJECT_ITEM           = 26,
   EFF_TARGET_ALL_ENEMY_IN_AREA_CHANNELED = 28,
   EFF_TARGET_MINION					= 32,
   EFF_TARGET_SINGLE_PARTY              = 35,
   EFF_TARGET_ALL_PARTY					= 37,
   EFF_TARGET_SELF_FISHING              = 39,
   EFF_TARGET_TOTEM_EARTH               = 41,
   EFF_TARGET_TOTEM_WATER               = 42,
   EFF_TARGET_TOTEM_AIR					= 43,
   EFF_TARGET_TOTEM_FIRE				= 44,
   EFF_TARGET_CHAIN						= 45,
   EFF_TARGET_DYNAMIC_OBJECT            = 47,//not sure exactly where is used
   EFF_TARGET_CURRENT_SELECTION         = 53,
   EFF_TARGET_PARTY_MEMBER		        = 57,
   EFF_TARGET_AREAEFFECT_PARTY_AND_CLASS  = 61,
} SpellEffectTarget;

typedef std::vector<uint64> TargetsList;
typedef void(Spell::*pSpellEffect)(uint32 i);


#define POWER_TYPE_HEALTH 0xFFFFFFFE
#define POWER_TYPE_MANA 0
#define POWER_TYPE_RAGE 1
#define POWER_TYPE_FOCUS 2
#define POWER_TYPE_ENERGY 3
// we have power type 15 and 31 :S

#define GO_FISHING_BOBBER 35591

#define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL 1000
class DummySpellHandler;
// Spell instance
class SERVER_DECL Spell
{
public:
	friend class DummySpellHandler;
	Spell( Object* Caster, SpellEntry *info, bool triggered, Aura* aur);
	~Spell();

	// Fills the targets at the area of effect
	void FillAllTargetsInArea(TargetsList *tmpMap,float srcx,float srcy,float srcz, float range);
	// Fills the targets at the area of effect. We suppose we already inited this spell and know the details
	void FillAllTargetsInArea(float srcx,float srcy,float srcz,uint32 ind);
	//get single Enemy as target
	uint64 GetSinglePossibleEnemy(float prange=0);
	//get single Enemy as target
	uint64 GetSinglePossibleFriend(float prange=0);
	//generate possible target list for a spell. Use as last resort since it is not acurate
	void GenerateTargets(SpellCastTargets *store_buff);
	// Fills the target map of the spell packet
	void FillTargetMap(uint32);
	// See if we hit the target or can it resist (evade/immune/resist on spellgo)
	bool DidHit(uint64 target);
	// Prepares the spell thats going to cast to targets
	void prepare(SpellCastTargets * targets);
	// Cancels the current spell
	void cancel();
	// Update spell state based on time difference
	void update(uint32 difftime);
	// Casts the spell
	void cast(bool);
	// Finishes the casted spell
	void finish();
	// Handle the Effects of the Spell
	void HandleEffects(uint64 guid,uint32 i);
	// Take Power from the caster based on spell power usage
	bool TakePower();
	// Has power?
	bool HasPower();
	// Trigger Spell function that triggers triggered spells
	void TriggerSpell();
	// Checks the caster is ready for cast
	uint8 CanCast(bool);
	// Checks the caster has needed items on it 
	int8 CheckItems();
	// Removes Reagents if cast is successful
	void RemoveItems();
	// Calculates the i'th effect value
	int32 CalculateEffect(uint32);
	// Handles Teleport function
	void HandleTeleport(uint32 id, Unit* Target);
	// Determines how much skill caster going to gain
	void DetermineSkillUp();
	// Increases cast time of the spell
	void AddTime(uint32 type);
	void AddCooldown();
	void AddStartCooldown();
	bool reflect(Unit *refunit);

	inline uint32 getState() { return m_spellState; }
	inline void SetUnitTarget(Unit *punit){unitTarget=punit;}

	// Send Packet functions
	void SendCastResult(int16 result);
	void SendSpellStart();
	void SendSpellGo();
	void SendLogExecute(uint32 damage, uint64 & targetGuid);
	void SendInterrupted(uint8 result);
	void SendChannelUpdate(uint32 time);
	void SendChannelStart(uint32 duration);
	void SendResurrectRequest(Player* target);
	void SendHealSpellOnPlayer(Player* caster, Player* target, uint32 dmg,bool critical);
	

	void HandleAddAura(uint64 guid);
	void writeSpellGoTargets( WorldPacket * data );
	void writeSpellMissedTargets( WorldPacket * data );

	SpellEntry * m_spellInfo;
	uint32 pSpellId;
	SpellCastTargets m_targets;

	void CreateItem(uint32 itemId);

	// Effect Handlers
	void SpellEffectNULL(uint32 i);
	void SpellEffectInstantKill(uint32 i);
	void SpellEffectSchoolDMG(uint32 i);
	void SpellEffectDummy(uint32 i);
	void SpellEffectTeleportUnits(uint32 i);
	void SpellEffectApplyAura(uint32 i);
	void SpellEffectPowerDrain(uint32 i);
	void SpellEffectHealthLeech(uint32 i);
	void SpellEffectHeal(uint32 i);
	void SpellEffectQuestComplete(uint32 i);
	void SpellEffectWeapondamageNoschool(uint32 i);
	void SpellEffectResurrect(uint32 i);
	void SpellEffectAddExtraAttacks(uint32 i);
	void SpellEffectDodge(uint32 i);
	void SpellEffectBlock(uint32 i);
	void SpellEffectParry(uint32 i);
	void SpellEffectCreateItem(uint32 i);
	void SpellEffectPersistentAA(uint32 i);
	void SpellEffectSummon(uint32 i);
	void SpellEffectLeap(uint32 i);
	void SpellEffectEnergize(uint32 i);
	void SpellEffectWeaponDmgPerc(uint32 i);
	void SpellEffectTriggerMissile(uint32 i);
	void SpellEffectOpenLock(uint32 i);
	void SpellEffectApplyAA(uint32 i);
	void SpellEffectLearnSpell(uint32 i);
	void SpellEffectSpellDefense(uint32 i);
	void SpellEffectDispel(uint32 i);
	void SpellEffectSummonWild(uint32 i);
	void SpellEffectSummonGuardian(uint32 i);
	void SpellEffectSkillStep(uint32 i);
	void SpellEffectSummonObject(uint32 i);
	void SpellEffectEnchantItem(uint32 i);
	void SpellEffectEnchantItemTemporary(uint32 i);
	void SpellEffectTameCreature(uint32 i);
	void SpellEffectSummonPet(uint32 i);
	void SpellEffectWeapondamage(uint32 i);
	void SpellEffectPowerBurn(uint32 i);
	void SpellEffectThreat(uint32 i);
	void SpellEffectTriggerSpell(uint32 i);
	void SpellEffectHealthFunnel(uint32 i);
	void SpellEffectPowerFunnel(uint32 i);
	void SpellEffectHealMaxHealth(uint32 i);
	void SpellEffectInterruptCast(uint32 i);
	void SpellEffectDistract(uint32 i);
	void SpellEffectPickpocket(uint32 i);
	void SpellEffectAddFarsight(uint32 i);
	void SpellEffectSummonPossessed(uint32 i);
	void SpellEffectCreateSummonTotem(uint32 i);
	void SpellEffectHealMechanical(uint32 i);
	void SpellEffectSummonObjectWild(uint32 i);
	void SpellEffectScriptEffect(uint32 i);
	void SpellEffectSanctuary(uint32 i);
	void SpellEffectAddComboPoints(uint32 i);
	void SpellEffectDuel(uint32 i);
    void SpellEffectStuck(uint32 i);
	void SpellEffectSummonPlayer(uint32 i);
	void SpellEffectActivateObject(uint32 i);
	void SpellEffectSummonTotem(uint32 i);
	void SpellEffectProficiency(uint32 i);
	void SpellEffectSendEvent(uint32 i);
	void SpellEffectSkinning(uint32 i);
	void SpellEffectCharge(uint32 i);
	void SpellEffectSummonCritter(uint32 i);
	void SpellEffectKnockBack(uint32 i);
	void SpellEffectInebriate(uint32 i);
	void SpellEffectFeedPet(uint32 i);
	void SpellEffectDismissPet(uint32 i);
	void SpellEffectReputation(uint32 i);
	void SpellEffectSummonObjectSlot(uint32 i);
	void SpellEffectDispelMechanic(uint32 i);
	void SpellEffectSummonDeadPet(uint32 i);
	void SpellEffectDestroyAllTotems(uint32 i);
	void SpellEffectSummonDemon(uint32 i);
	void SpellEffectAttackMe(uint32 i);
	void SpellEffectSkill(uint32 i);
	void SpellEffectApplyPetAura(uint32 i);
	void SpellEffectDummyMelee(uint32 i);
	void SpellEffectProspecting(uint32 i);
	void SpellEffectOpenLockItem(uint32 i);
	void SpellEffectSelfResurrect(uint32 i);
	void SpellEffectDisenchant(uint32 i);
	void SpellEffectWeapon(uint32 i);
	void SpellEffectDefense(uint32 i);
	void SpellEffectDualWield(uint32 i);
	void SpellEffectSkinPlayerCorpse(uint32 i);
	void SpellEffectResurrectNew(uint32 i);
	void SpellEffectTranformItem(uint32);
	void SpellEffectEnvironmentalDamage(uint32);
	void SpellEffectLearnPetSpell(uint32 i);
	void SpellEffectEnchantHeldItem(uint32 i);
	void SpellEffectAddHonor(uint32 i);
	void SpellEffectSpawn(uint32 i);

	void Heal(int32 amount);

	GameObject *g_caster;
	Unit * u_caster;
	Item * i_caster;
	Player *p_caster;
	Object* m_caster;

	
	
	// get the diet flags for pet food
	inline uint32 GetPetFoodFlags(const char* m_string)
	{
		if (strstr(m_string, "Meat")   || strstr(m_string, "meat"))
			return 1;
		if (strstr(m_string, "Fish")   || strstr(m_string, "fish"))
			return 2;
		if (strstr(m_string, "Cheese") || strstr(m_string, "cheese"))
			return 4;
		if (strstr(m_string, "Bread")  || strstr(m_string, "bread"))
			return 8;
		if (strstr(m_string, "Fungus") || strstr(m_string, "fungus"))
			return 16;
		if (strstr(m_string, "Fruit")  || strstr(m_string, "fruit"))
			return 32;
		return 0;
	}
	
	inline uint32 GetType()//0 melee,1 magic ,2 ranged
	{	  
		  //this is dirty fix, we must use weapon class to define dmg type

		if(m_spellInfo->Id == SPELL_RANGED_BOW)
			return SPELL_TYPE_RANGED;

		if(m_spellInfo->Id == SPELL_RANGED_GUN)
			return SPELL_TYPE_RANGED;

		if(m_spellInfo->Id == SPELL_RANGED_CROSSBOW)
			return SPELL_TYPE_RANGED;

		if(m_spellInfo->Id == SPELL_RANGED_THROW)
			return SPELL_TYPE_RANGED;
		

		if(m_spellInfo->Id == SPELL_RANGED_WAND)
			return SPELL_TYPE_RANGED;

 
		if(m_spellInfo->Spell_Dmg_Type ==1)//1=Magic, 2=Melee, 3=Ranged
			return 1;
		if(m_spellInfo->Spell_Dmg_Type ==2)
			return 0;
		else return 2;
	}

	std::vector<uint64> UniqueTargets;
	std::vector<uint64> MissedTargets;

	inline Item* GetItemTarget() { return itemTarget; }
	inline Unit* GetUnitTarget() { return unitTarget; }
	inline Player* GetPlayerTarget() { return playerTarget; }
	inline GameObject* GetGameObjectTarget() { return gameObjTarget; }

	uint32 chaindamage;
	// -------------------------------------------

	bool IsAspect();
	bool IsSeal();

	inline uint32 GetDuration()
	{
		if(bDurSet)return Dur;
		bDurSet=true;
		
		
		if(m_spellInfo->DurationIndex!=427)//resurrection sickness, has wierd duration 
		{
				SpellDuration *sd=sSpellDuration.LookupEntry(m_spellInfo->DurationIndex);
			if(m_spellInfo->DurationIndex)
				Dur =::GetDuration(sd); 
			else 
				Dur = (uint32)-1;
			if(p_caster)  
			{
				uint32 cp=p_caster->m_comboPoints;
				if(cp)
				{
					uint32 bonus=(cp*(sd->Duration3-sd->Duration1))/5;
					if(bonus)
					{
						Dur+=bonus;
						m_requiresCP=true;
					}
				}
			}

			if(m_spellInfo->SpellGroupType && u_caster)
			{
				SM_FIValue(u_caster->SM_FDur,(int32*)&Dur,m_spellInfo->SpellGroupType);
				SM_PIValue(u_caster->SM_PDur,(int32*)&Dur,m_spellInfo->SpellGroupType);
			}
		}
		else
		{
			if(u_caster->getLevel()<11) Dur=0;
			else if(u_caster ->getLevel()<=20)
				Dur =(u_caster->getLevel()-10)*60*1000;
			else Dur =10*60*1000;
		}
		return Dur;
	}

	inline float GetRadius(uint32 i)
	{
		if(bRadSet[i])return Rad[i];
		bRadSet[i]=true;
		Rad[i]=::GetRadius(sSpellRadius.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
		if(m_spellInfo->SpellGroupType && u_caster)
		{
			SM_FFValue(u_caster->SM_FRadius,&Rad[i],m_spellInfo->SpellGroupType);
			SM_PFValue(u_caster->SM_PRadius,&Rad[i],m_spellInfo->SpellGroupType);
		}

		return Rad[i];
	}

	bool IsStealthSpell();
	bool IsInvisibilitySpell();
	
	int32 damage;
	Aura* m_triggeredByAura;

	bool m_triggeredSpell;
	bool m_AreaAura;
	uint32 TriggerSpellId;  // used to set next spell to use
	uint64 TriggerSpellTarget; // used to set next spell target
	bool m_requiresCP;
	float m_castPositionX;
	float m_castPositionY;
	float m_castPositionZ;
   
	int32 damageToHit;
	uint32 castedItemId;
	bool judgement;

	void SendCastSuccess(Object * target);
	void SendCastSuccess(const uint64& guid);

protected:
	bool m_usesMana;
	bool failed;//for 5sr

	uint32 m_spellState;
	int32 m_castTime;
	int32 m_timer;
	bool m_delayed;
	

	// Current Targets to be used in effect handler
	Unit* unitTarget;
	Item* itemTarget;
	GameObject* gameObjTarget;
	Player* playerTarget;
	Corpse* corpseTarget;
	uint32 add_damage;

	int8 cancastresult;
	uint32 Dur;
	bool bDurSet;
	float Rad[3];
	bool bRadSet[3];
	void _DamageRangeUpdate();

private:
	TargetsList m_targetUnits[3];
	void SafeAddTarget(TargetsList* tgt,uint64 guid);
	void SafeAddMissedTarget(uint64 guid);
	friend class DynamicObject;
	void DetermineSkillUp(uint32 skillid,uint32 targetlevel);
	void DetermineSkillUp(uint32 skillid);
};

void ApplyDiminishingReturnTimer(uint32 * Duration, Unit * Target, SpellEntry * spell);
void UnapplyDiminishingReturnTimer(Unit * Target, SpellEntry * spell);
uint32 GetDiminishingGroup(uint32 NameHash);

#endif
